package logica.users;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import logica.exceptions.EmailAlreadyExistException;
import logica.exceptions.InvalidDataException;
import logica.exceptions.RequiredDataException;
import logica.exceptions.UserAlreadyExistException;
import logica.exceptions.UserDoesNotContainProductsException;
import logica.exceptions.UserDoesNotExistException;
import logica.exceptions.UserNotAuthenticatedException;
import logica.interfaces.UserIF;

import persistencia.FachadaPersistence;

/**
 * Controlador dos usuarios do sistema. Ele gerencia as acoes referentes aos
 * usuarios do sistema.
 */
public class UserControl {

	// Fachada persistente
	private FachadaPersistence fachadaPersist;

	// Lista de usuarios logados
	private List<String> usersLogin;

	/**
	 * Construtor de um controlador de usuarios. Ele gerencia as acoes
	 * referentes aos usuarios do sistema.
	 */
	public UserControl() {
		this.fachadaPersist = FachadaPersistence.getInstance();
		this.usersLogin = new ArrayList<String>();
	}

	/**
	 * Cria um novo usuario e o adiciona no sistema.
	 *
	 * @param login
	 *            O login do novo usuario (este nao deve ser igual a um ja
	 *            existente).
	 * @param name
	 *            O nome do novo usuario.
	 * @param email
	 *            O email do usuario.
	 * @param password
	 *            A senha do usuario.
	 * @param address
	 *            O endereco do usuario.
	 * @param cpfNumber
	 *            O numero de cpf do usuario.
	 * @param phoneNumber
	 *            O numero de telefone do usuario.
	 * @throws InvalidDataException
	 *             Se algum dos dados for invalido.
	 * @throws RequiredDataException
	 *             Se algum dos dados for nulo ou vazio.
	 * @throws UserAlreadyExistException
	 *             Se o usuario criado ja existir no sistema.
	 */
	public void createUser(String login, String name, String email,
			String password, String address, String cpfNumber,
			String phoneNumber) throws InvalidDataException,
			RequiredDataException, UserAlreadyExistException {

		UserIF newUser = new User(login, name, email, password, address,
				cpfNumber, phoneNumber);
		this.fachadaPersist.addUser(newUser);
	}

	/**
	 * Faz o login de um usuario no sistema.
	 *
	 * @param login
	 *            O login do usuario.
	 * @param senha
	 *            A senha do usuario.
	 * @return A sessao do usuario, corresponde ao login do mesmo.
	 *
	 * @throws UserDoesNotExistException
	 *             Se o usuario nao existir.
	 */
	public String doLogin(String login, String senha)
			throws UserDoesNotExistException {
		UserIF user = this.fachadaPersist.getUser(login);
		if (user == null)
			throw new UserDoesNotExistException();

		if (user.getPassword().equals(senha)) {
			this.usersLogin.add(login);
			return login;
		} else
			throw new UserDoesNotExistException();
	}

	/**
	 * Faz logout do usuario no sistema.
	 *
	 * @param login
	 *            O login do usuario.
	 * @throws UserNotAuthenticatedException
	 *             Se o usuario nao estiver autenticado.
	 */
	public void doLogout(String login) throws UserNotAuthenticatedException {
		if (!usersLogin.contains(login))
			throw new UserNotAuthenticatedException();
		this.usersLogin.remove(login);
	}

	/**
	 * Retorna true se o login do usuario corresponde ao de alguem logado no
	 * sistema.
	 *
	 * @param login
	 *            O login do usuario.
	 * @return True se o usuario esiver logado, false em caso contrario.
	 */
	public boolean isLogin(String login) {
		return this.usersLogin.contains(login);
	}

	/**
	 * Retorna o nome do usuario
	 *
	 * @param userLogin
	 *            O login do usuario.
	 * @return o valor do atributo.
	 */
	public String getUserName(String userLogin) {
		UserIF user = fachadaPersist.getUser(userLogin);
		return user.getName();
	}

	/**
	 * Retorna o email do usuario
	 *
	 * @param userLogin
	 *            O login do usuario.
	 * @return o valor do atributo.
	 */
	public String getUserEmail(String userLogin) {
		UserIF user = fachadaPersist.getUser(userLogin);
		return user.getEmail();

	}

	/**
	 * Retorna o cpf do usuario
	 *
	 * @param userLogin
	 *            O login do usuario.
	 * @return o valor do atributo.
	 */
	public String getUserCpfNumber(String userLogin) {
		UserIF user = fachadaPersist.getUser(userLogin);
		return user.getCpfNumber();

	}

	/**
	 * Retorna o endereco do usuario
	 *
	 * @param userLogin
	 *            O login do usuario.
	 * @return o valor do atributo.
	 */
	public String getUserAddress(String userLogin) {
		UserIF user = fachadaPersist.getUser(userLogin);
		return user.getAddress();

	}

	/**
	 * Retorna o status do usuario
	 *
	 * @param userLogin
	 *            O login do usuario.
	 * @return o valor do atributo.
	 */
	public int getUserStatus(String userLogin) {
		UserIF user = fachadaPersist.getUser(userLogin);
		return user.getStatus();

	}

	/**
	 * Retorna o telefone do usuario
	 *
	 * @param userLogin
	 *            O login do usuario.
	 * @return o valor do atributo.
	 */
	public String getUserPhoneNumber(String userLogin) {
		UserIF user = fachadaPersist.getUser(userLogin);
		return user.getPhoneNumber();

	}

	/**
	 * Altera o nome do usuario
	 *
	 * @param userLogin
	 *            O login do usuario.
	 * @param value
	 *            novo valor.
	 * @throws RequiredDataException
	 *             Se o nome for nulo ou vazio.
	 */
	public void setUserName(String userLogin, String value)
			throws RequiredDataException {
		UserIF user = fachadaPersist.getUser(userLogin);
		user.setName(value);
	}

	/**
	 * Altera o email do usuario
	 *
	 * @param userLogin
	 *            O login do usuario.
	 * @param value
	 *            novo valor.
	 * @throws RequiredDataException
	 *             Se o email for nulo ou invalido.
	 * @throws InvalidDataException
	 *             Se o email for invalido.
	 * @throws EmailAlreadyExistException
	 *             Se o email ja existir no sistema.
	 */
	public void setUserEmail(String userLogin, String value)
			throws RequiredDataException, InvalidDataException,
			EmailAlreadyExistException {
		// temporario... ao colocar o iterador vai funfar blz.
		List<UserIF> users = fachadaPersist.getAllUsers();
		for (UserIF user : users) {
			if (user.getEmail().equals(value))
				throw new EmailAlreadyExistException();
		}

		UserIF user = fachadaPersist.getUser(userLogin);
		user.setEmail(value);
	}

	/**
	 * Altera o endereco do usuario
	 *
	 * @param userLogin
	 *            O login do usuario.
	 * @param value
	 *            novo valor.
	 * @throws RequiredDataException
	 *             Se o endereco for nulo ou vazio.
	 */
	public void setUserAddress(String userLogin, String value)
			throws RequiredDataException {

		UserIF user = fachadaPersist.getUser(userLogin);
		user.setAddress(value);

	}

	/**
	 * Altera o telefone do usuario
	 *
	 * @param userLogin
	 *            O login do usuario.
	 * @param value
	 *            novo valor.
	 * @throws RequiredDataException
	 *             Se o telefone for invalido.
	 */
	public void setUserPhoneNumber(String userLogin, String value)
			throws RequiredDataException {
		UserIF user = fachadaPersist.getUser(userLogin);
		user.setPhoneNumber(value);

	}

	/**
	 * Remove todos os produtos de um usuario.
	 *
	 * @param userSession
	 *            A sessao que realizara a acao.
	 * @throws UserDoesNotContainProductsException
	 *             SE o usuario nao contiver produto algum.
	 */
	public void removeAllProducts(String userLogin)
			throws UserDoesNotContainProductsException {
		UserIF user = fachadaPersist.getUser(userLogin);
		user.removeAllProducts();
	}

	/**
	 * Deleta um usuario do sistema.
	 *
	 * @param session
	 *            O id da sessao do usuario que sera deletado do sistema.
	 *
	 */
	public void deleteUser(String userLogin) {
		fachadaPersist.removeUser(userLogin);

	}

	/**
	 * Deleta um produto do sistema.
	 *
	 * @param userLogin
	 *            O login do usuario.
	 * @param prductId
	 *            O identificador do produto.
	 * @throws UserDoesNotContainProductsException
	 *             Se o usuario nao contiver o produto.
	 */
	public void deleteProduct(String userLogin, String prductId)
			throws UserDoesNotContainProductsException {
		UserIF user = fachadaPersist.getUser(userLogin);
		user.removeProducts(prductId);
	}

	/**
	 * Adiciona um produto a um usuario.
	 *
	 * @param userLogin
	 *            O login do usuario.
	 * @param productId
	 *            O id do produto.
	 */
	public void addProductInUser(String userLogin, String productId) {
		UserIF user = this.fachadaPersist.getUser(userLogin);
		user.addProduct(productId);
	}

	/**
	 * Retorna os ids de todos os produtos de um usuario.
	 *
	 * @param userLogin
	 *            O login do usuario.
	 * @return A lista de ids de produtos.
	 */
	public List<String> getAllProducts(String userLogin) {
		UserIF user = this.fachadaPersist.getUser(userLogin);
		return user.getAllProducts();
	}

	/**
	 * Retorna o produto especifico do indice do usuario.
	 *
	 * @param login
	 *            O login do usuario.
	 * @param index
	 *            O indice do produto.
	 * @return O login do produto especifico.
	 */
	public String listProduct(String login, int index) {
		UserIF user = this.fachadaPersist.getUser(login);
		return user.getAllProducts().get(index);
	}

	/**
	 * Diminui o status de um usuario.
	 *
	 * @param login
	 *            O login do usuario.
	 */
	public void setUserStatusDown(String login) {
		UserIF user = this.fachadaPersist.getUser(login);
		user.setStatusDown();
	}

	/**
	 * Aumenta o status do usuario.
	 *
	 * @param login
	 *            O login do usuario.
	 */
	public void setUserStatusHigh(String login) {
		UserIF user = this.fachadaPersist.getUser(login);
		user.setStatusUp();

	}

	public void notifyWinner(String login, String auctionName,
			String product) {
		UserIF user = this.fachadaPersist.getUser(login);
		user.notifyWinnerAuction(auctionName, product);;

	}

	/**
	 * Persiste todos os dados no sistema.
	 */
	public void persistAllData() {
		this.fachadaPersist.persistAll();

	}
}
